﻿#pragma once


#include <memory>
#include <string>
#include <ostream>
#include <tuple>
#include <utility>
#include <nlohmann/json.hpp>

// 模块的模板
class BasePlugModule {
public:

    typedef std::shared_ptr<BasePlugModule> ptr;

    typedef std::weak_ptr<BasePlugModule> weak_ptr;

    enum Type {
        ///@brief 动态模块
        MODULE = 0,

        ///@brief 静态模块
        ROCK = 1,
    };

    NLOHMANN_JSON_SERIALIZE_ENUM(Type, {
        { Type::MODULE, "module" },
        { Type::ROCK, "rock" }
    });

    BasePlugModule(std::string mId,
                   std::string mName,
                   std::string mVersion,
                   std::string mFilename,
                   bool mState,
                   Type mType)
            : m_id(std::move(mId)),
              m_name(std::move(mName)),
              m_version(std::move(mVersion)),
              m_filename(std::move(mFilename)),
              m_state(mState),
              m_type(mType) {}

    BasePlugModule(std::string name,
                   std::string version,
                   std::string filename,
                   Type type = MODULE)
            : m_id(name + "/" + version),
              m_name(std::move(name)),
              m_version(std::move(version)),
              m_filename(std::move(filename)),
              m_state(false),
              m_type(type) {}

    // null
    BasePlugModule()
            : m_id("undefined"),
              m_name("undefined"),
              m_version("undefined"),
              m_filename("undefined"),
              m_state(false),
              m_type(Type::MODULE) {}

    virtual void OnBeforeArgsParse(int argc, char **argv) {}

    virtual void OnAfterArgsParse(int argc, char **argv) {}

    virtual bool OnLoad() { return false; }

    virtual bool OnUnload() { return false; }

    virtual bool OnConnect(/*::Stream::ptr stream*/) { return false; }

    virtual bool OnDisconnect(/*::Stream::ptr stream*/) { return false; }

    virtual bool OnServerReady() { return false; }

    virtual bool OnServerUp() { return false; }

    virtual bool HandleRequest(/*::Message::ptr req
            ,::Message::ptr rsp
            ,::Stream::ptr stream*/) { return false; }

    virtual bool HandleNotify(/*::Message::ptr notify
            ,::Stream::ptr stream*/) { return false; }

    bool IsNull() const { return "undefined" == m_id; }

    const std::string &GetId() const { return m_id; }

    const std::string &GetName() const { return m_name; }

    const std::string &GetVersion() const { return m_version; }

    const std::string &GetFilename() const { return m_filename; }

    bool GetState() const { return m_state; }

    Type GetType() const { return m_type; }

    void SetFilename(const std::string &v) { m_filename = v; }

public:

    /// @brief id
    std::string m_id;

    /// @brief dll别名,全局唯一性
    std::string m_name;

    /// @brief 版本号
    std::string m_version;

    /// @brief 文件名称
    std::string m_filename;

    /// @brief 是否已发布
    bool m_state;

    /// @brief 类型
    Type m_type;

public:
    friend std::ostream &operator<<(std::ostream &os, const BasePlugModule &aModule) {
        os << "m_id: " << aModule.m_id << " m_name: " << aModule.m_name << " m_version: " << aModule.m_version
           << " m_filename: " << aModule.m_filename << " m_state: " << aModule.m_state << " m_type: "
           << aModule.m_type;
        return os;
    }

    friend std::ostream &operator<<(std::ostream &os, const BasePlugModule *aModule) {
        os << "m_id: " << aModule->m_id << " m_name: " << aModule->m_name << " m_version: " << aModule->m_version
           << " m_filename: " << aModule->m_filename << " m_state: " << aModule->m_state << " m_type: "
           << aModule->m_type;
        return os;
    }


    bool operator==(const BasePlugModule &rhs) const {
        return std::tie(m_id, m_name, m_version, m_filename, m_state, m_type) ==
               std::tie(rhs.m_id, rhs.m_name, rhs.m_version, rhs.m_filename, rhs.m_state, rhs.m_type);
    }

    bool operator!=(const BasePlugModule &rhs) const {
        return !(rhs == *this);
    }

public:
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(BasePlugModule, m_id, m_name, m_version, m_filename, m_state, m_type)
};

